package com.logos.musicframe.aop;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.time.StopWatch;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author logos
 * date 2025/6/15 22:19
 * @version v1.0
 * @Package com.logos.musicframe.aop
 */
@Aspect
@Component
public class FacadeAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(FacadeAspect.class);

    //所有controller方法
    @Around("execution(* com.logos.musicframe.controller..*.*(..))||execution(* com.logos.musicframe.cache.*.initCache(..))")
    public Object facade(ProceedingJoinPoint pjp) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        Object[] args = pjp.getArgs();
        String className = method.getDeclaringClass().getName().split("\\.")[method.getDeclaringClass().getName().split("\\.").length - 1];
        LOGGER.info("start to execute , " + className + ".method = " + method.getName() + " , args = " + JSON.toJSONString(args));
        // 目标方法执行
        Object response = null;
        try {
            response = pjp.proceed();
        } catch (Throwable throwable) {
            printLog(stopWatch, method, args, "failed to execute", throwable);
        }
        printLog(stopWatch, method, args, className + " end to execute", null);
        return response;
    }

    /**
     * 日志打印
     *
     * @param stopWatch
     * @param method
     * @param args
     * @param action
     */
    private void printLog(StopWatch stopWatch, Method method, Object[] args, String action, Throwable throwable) {
        try {
            //因为此处有JSON.toJSONString，可能会有异常，需要进行捕获，避免影响主干流程
            LOGGER.info(getInfoMessage(action, stopWatch, method, args, throwable), throwable);
            // 如果校验失败，则返回一个失败的response
        } catch (Exception e1) {
            LOGGER.error("log failed", e1);
        }
    }

    /**
     * 统一格式输出，方便做日志统计
     * <p>
     * *** 如果调整此处的格式，需要同步调整日志监控 ***
     *
     * @param action    行为
     * @param stopWatch 耗时
     * @param method    方法
     * @param args      参数
     * @return 拼接后的字符串
     */
    private String getInfoMessage(String action, StopWatch stopWatch, Method method, Object[] args, Throwable exception) {

        StringBuilder stringBuilder = new StringBuilder(action);
        stringBuilder.append(" ,method = ");
        stringBuilder.append(method.getName());
        stringBuilder.append(" ,cost = ");
        stringBuilder.append(stopWatch.getTime()).append(" ms");
        if (exception != null) {
            stringBuilder.append(" ,success = ");
            stringBuilder.append(false);
        }
        stringBuilder.append(" ,args = ");
        stringBuilder.append(JSON.toJSONString(Arrays.toString(args)));

        if (exception != null) {
            stringBuilder.append(" ,exception = ");
            stringBuilder.append(exception.getMessage());
        }

        return stringBuilder.toString();
    }


}
